import datetime
import hashlib
import secrets
import time

from flask import Blueprint, render_template, jsonify, request, current_app, make_response, redirect
from jinja2 import TemplateNotFound

from app.application.auth.login_service import AuthService
from app.utils.verify_code import VerifyCode
from app.models.sys_manage.user import User
from app.utils.mysql_util import MySQLTool
from app.utils.redis_util import RedisTool

auth = Blueprint('auth', __name__,
                 template_folder='auth')


@auth.get('/')
@auth.get('/login')  # 登录页面
def login():
    # 获取错误消息
    message = request.args.get('message')
    return render_template('login.html', message=message)


@auth.post('/login')  # 检验验证码，账号密码
def verify():
    # 从当前flask实例中获取redis，mysql工具类
    # redis_tool = current_app.extensions['redis_tool']
    # mysql_tool = current_app.extensions['mysql_tool']
    # 从工具类中获取mysql_tool，redis_tool实例
    mysql_tool = MySQLTool.get_instance()
    redis_tool = RedisTool.get_instance()
    username = request.form.get("username")
    password = request.form.get("password")
    codeId = request.form.get("codeId")
    captcha = request.form.get("captcha")
    auth_service = AuthService(mysql_tool, redis_tool)
    error_message, current_user = auth_service.verify_login(username, password, codeId, captcha)
    # error_message 为不为空则返回错误信息，否则放行==》登录成功
    if error_message:
        """
        当有错误消息需要返回时，通过 make_response 函数创建一个响应对象，将 JSON 化后的错误消息放入其中，然后设置响应头的 Content-Type 为 application/json，
        这样前端就能知道这是一个 JSON 格式的数据，应该按照 JSON 数据的处理方式来操作。
        """
        response = make_response(jsonify({"error": error_message}))
        response.headers['Content-Type'] = 'application/json'
        return response, 400
    # return render_template('index.html',current_user = current_user)

    # 通过验证，返回token
    token = generate_token()
    # 将token，用户id存入redis中。登录凭据10分钟自动过期
    redis_tool.set_value(token, current_user.user_id, ex=15 * 60)
    resp = make_response()
    resp.set_cookie(
        "token",
        token,
        # max_age=900,  # 15分钟 = 900秒
        path='/',  # 整个网站都可以访问
        httponly=True,  # 防止XSS攻击
        domain=None,  # 允许所有子域名访问
        secure=False,  # 允许HTTP访问（生产环境建议设为True）
        samesite='Lax'  # 允许从外部链接打开新标签页时携带Cookie
    )
    return resp


def generate_token():
    """
    生成随机字符串作为token值
    :return: hashed_token
    """
    random_string = secrets.token_hex(16) + str(time.time())
    hashed_token = hashlib.sha256(random_string.encode()).hexdigest()
    return hashed_token


@auth.get('/index')
def index():
    user_token = request.cookies.get('token')
    redis_tool = RedisTool.get_instance()
    mysql_tool = MySQLTool.get_instance()
    user_id = redis_tool.get_value(user_token)
    login_users = mysql_tool.query_data(User, user_id=user_id)  # 返回的是列表
    if not login_users:
        return redirect('/login?message=用户信息获取失败，请重新登录！')
    login_user = login_users[0]  # 获取第一个用户
    return render_template('index.html', current_user=User(user_id=user_id, username=login_user.username))


@auth.get('/getCaptcha')  # 获取验证码
def getCaptcha():
    redis_tool = current_app.extensions['redis_tool']
    auth_service = AuthService(None, redis_tool)
    return jsonify(auth_service.generate_captcha())
